/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mindbox.mueblesalpes.negocio.compras;

import com.mindbox.mueblesalpes.negocio.entity.CategoriaValor;
import com.mindbox.mueblesalpes.negocio.entity.Cliente;
import com.mindbox.mueblesalpes.negocio.entity.Compra;
import com.mindbox.mueblesalpes.negocio.entity.Mueble;
import com.mindbox.mueblesalpes.negocio.entity.MuebleInventario;
import com.mindbox.mueblesalpes.negocio.entity.Usuario;
import com.mindbox.mueblesalpes.negocio.entity.Venta;
import com.mindbox.mueblesalpes.negocio.exception.TiendaException;
import com.mindbox.mueblesalpes.negocio.persistence.PersistenciaLocal;
import com.mindbox.mueblesalpes.negocio.producto.IProductoService;
import static com.mindbox.mueblesalpes.negocio.utilidades.UtilidadesCompra.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

/**
 *
 * @author jsanchez
 */
@Stateful
@TransactionManagement(TransactionManagementType.CONTAINER)
public class CarritoComprasBean implements CarritoComprasLocal {

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method" or "Web Service > Add Operation")
    /**
     * Mueble seleccionado actualmente.
     */
    private Mueble muebleSeleccionado;
    /**
     * Carrito de compras.
     */
    private List<Compra> carritoCompras;
    /**
     * Representa a la nuevaVenta que se va a realizar en el momento.
     */
    private Venta venta;
    /**
     * Categorias de valor de la compra
     */
    private List<CategoriaValor> categoriasValor;
    private double subtotal;
    private double valorTotal;
    private String descripcionVenta;
    @EJB
    private IProductoService producto;
    @EJB
    private PersistenciaLocal persistencia;

    /**
     * Inicializa el carrito de compras
     */
    public CarritoComprasBean() {
    }

    /**
     * Se ejecuta despues de contruir este objeto.
     */
    @PostConstruct
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void init() {
        this.carritoCompras = new ArrayList<Compra>();
        this.categoriasValor = new ArrayList<CategoriaValor>();
        this.setValorTotal(0.0);
        this.setSubtotal(0.0);
        this.setMuebleSeleccionado(null);
        this.setVenta(null);
        this.setDescripcionVenta(null);
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public Mueble getMuebleSeleccionado() {
        return muebleSeleccionado;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void setMuebleSeleccionado(Mueble muebleSeleccionado) {
        this.muebleSeleccionado = muebleSeleccionado;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public List<Compra> getCarritoCompras() {
        return carritoCompras;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void setCarritoCompras(List<Compra> carritoCompras) {
        this.carritoCompras = carritoCompras;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public Venta getVenta() {
        return this.venta;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void setVenta(Venta venta) {
        this.venta = venta;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void setCategoriasValor(List<CategoriaValor> categoriasValor) {
        this.categoriasValor = categoriasValor;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public List<CategoriaValor> getCategoriasValor() {
        return this.categoriasValor;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public double getSubtotal() {
        return subtotal;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void setSubtotal(double subtotal) {
        this.subtotal = subtotal;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public double getValorTotal() {
        return valorTotal;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void setValorTotal(double valorTotal) {
        this.valorTotal = valorTotal;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public String getDescripcionVenta() {
        return descripcionVenta;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void setDescripcionVenta(String descripcionVenta) {
        this.descripcionVenta = descripcionVenta;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void validarAgregarMuebleSeleccionado() {
        // Se verifica si se debe agregar un producto al carrito
        if (this.getMuebleSeleccionado() != null) {

            Compra compraActual = null;
            for (int i = 0; i < this.getCarritoCompras().size() && compraActual == null; i++) {
                if (this.getCarritoCompras().get(i).getMueble().equals(this.muebleSeleccionado)) {
                    compraActual = this.getCarritoCompras().get(i);
                }
            }

            if (compraActual == null) {
                //Se debe agregar al carrito.
                this.getCarritoCompras().add(new Compra(this.getMuebleSeleccionado(), 1,
                        this.producto.consultarMuebleInventarioPorMueble(this.getMuebleSeleccionado()).getPrecio()));
            } else {
                // Se debe actualizar la catnidad de la compra
                compraActual.setCantidad(compraActual.getCantidad() + 1);
            }
            // Se coloca el mueble seleccionado en null para no volverlo a adicionar
            setMuebleSeleccionado(null);
            // Se debe calcular todos los valores:
            this.setSubtotal(calcularSubtotalCompra(this.getCarritoCompras()));
            this.setCategoriasValor(calcularValorCategoriasCompra(this.getSubtotal()));
            this.setValorTotal(calcularValorTotalCompra(this.getCategoriasValor()));
        }
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void realizarVenta(Cliente cliente, Usuario usuario) {
        try {
            Venta nuevaVenta = new Venta();

            for (CategoriaValor cv : this.getCategoriasValor()) {
                cv.setVenta(nuevaVenta);
            }
            nuevaVenta.setCategoriasValor(this.getCategoriasValor());

            for (Compra c : this.getCarritoCompras()) {
                c.setVenta(nuevaVenta);
            }
            nuevaVenta.setCompras(this.getCarritoCompras());

            nuevaVenta.setCliente(cliente);
            nuevaVenta.setUsuario(usuario);
            nuevaVenta.setValorTotal(this.getValorTotal());

            persistencia.create(nuevaVenta);
            nuevaVenta.setReferencia(nuevaVenta.getIdVenta() + "");
            persistencia.update(nuevaVenta);

            this.setVenta((Venta) nuevaVenta.clone());
            this.setDescripcionVenta(calcularDescripcionVenta(this.getVenta()));
        } catch (Exception ex) {
            Logger.getLogger(CarritoComprasBean.class.getName()).log(Level.SEVERE, null, ex);
            throw new TiendaException("Error al crear la venta:" + ex.getMessage());
        }
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void realizarPago() {
        try {
            enviarCorreo("mindbox09@gmail.com", "Compra de Productos", "Su compra ha sido exitosa:" + getDescripcionVenta());
            this.getVenta().setVentaPagada(true);
            // Se disminuye del inventario
            for (Compra compra : this.getVenta().getCompras()) {
                MuebleInventario inventario = producto.consultarMuebleInventarioPorMueble(compra.getMueble());
                inventario.setCantidad(inventario.getCantidad() - compra.getCantidad());
                persistencia.update(inventario);
            }
            persistencia.update(this.getVenta());
        } catch (Exception ex) {
            Logger.getLogger(CarritoComprasBean.class.getName()).log(Level.SEVERE, null, ex);
            throw new TiendaException("Error al realizar el pago:" + ex.getMessage());
        }
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    @PreDestroy
    public void cancelarPago() {
        try {
            if (this.getVenta() != null) {
                if (!this.venta.isVentaPagada()) {
                    this.persistencia.delete(this.getVenta());
                } else {
                    throw new TiendaException("La venta ya fue pagada.");
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(CarritoComprasBean.class.getName()).log(Level.SEVERE, null, ex);
            throw new TiendaException("Error al cancelar el pago:" + ex.getMessage());
        } finally {
            terminarTransaccion();
        }
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void terminarTransaccion() {
        this.init();
    }
}